// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud

namespace BrainTechLLC.Communication
{
    using System;
    using System.ComponentModel;
    using System.Net.Sockets;
    using System.Threading;

    using BrainTechLLC.ThreadSafeObjects;

#if NO_SILVERLIGHT
    [Browsable(true)]
#endif
    public class OutgoingConnection : ConnectionBase, ICommClientIssueCommands, IGameClient
    {
        #region Constructors

        public OutgoingConnection()
        {
        }

        public OutgoingConnection(EventHandler<ObjectEventArgs<ICommunicationsMessage>> messageReceivedEvent)
            : base()
        {
            MessageReceived += new EventHandler<ObjectEventArgs<ICommunicationsMessage>>(messageReceivedEvent);
        }

        #endregion Constructors

        #region Properties

        public IGameClient GameClient
        {
            get { return this as IGameClient; }
        }

        public Thread ListenIncomingThread
        {
            get;
            set;
        }

        public Thread ProcessMessagesThread
        {
            get;
            set;
        }

        public Thread SendOutgoingThread
        {
            get;
            set;
        }

        public bool WantExit
        {
            get;
            set;
        }

        #endregion Properties

        #region Methods

        public override void CloseConnection()
        {
            NeedsClosing = true;
            WantExit = true;
            TcpClientConnection.CloseAndCleanup();
        }

        public bool Connect(string hostName, int portNumber, bool wantThrowException)
        {
#if NO_SILVERLIGHT

            TcpClientConnection = new TCPIPSocketProtocol();

            try { TcpClientConnection.Connect(hostName, portNumber, true); }
            catch (Exception ex)
            {
                if (wantThrowException)
                    throw new Exception("Error trying to connect to " + hostName + " on port " + portNumber.ToString(), ex);
                else
                    return false;
            }

            ListenIncomingThread = new ThreadStart(ListenIncoming).CreateAndRunThread();
            ProcessMessagesThread = new ThreadStart(ProcessMessages).CreateAndRunThread();
            SendOutgoingThread = new ThreadStart(SendOutgoing).CreateAndRunThread();

            return true;
#else
            return false;
#endif
        }

        public void IssueCommand(object o, int transmissionType)
        {
            Message message = new Message(o, transmissionType, new MessageHeader());
            byte[] bytes = message.ReadBytesForTransmission();
            if (bytes != null) { EnqueueForSend(bytes); }
        }

        internal void ListenIncoming()
        {
            while (!WantExit) { if (CheckBytesIncoming() == 0) { Thread.Sleep(100); } }
        }

        internal void ProcessMessages()
        {
            while (!WantExit) { if (!GetNextFullMessage()) { Thread.Sleep(100); } }
        }

        internal void SendOutgoing()
        {
            while (!WantExit) { if (SendBytesOutgoing() == 0) { Thread.Sleep(100); } }
        }

        #endregion Methods
    }
}